/* JSXML XML Tools - REXML Lite
Released under the LGPL license - created by Level Three Solutions
http://jsxml.homestead.com/
Ver 1.2 Jun 18 2001
Copyright 2000 Peter Tracey

A light-weight regular expression-based XML parser.
Workaround for Bug 611042: request.response.xml pulled from request module api.
Converts an XML string from request.response.text to an XML document in object form.

Changes: George Bradt
         1. bypass the xml declaration tag.
         2. added a new method childElementsNamed().

Objects:

    XMLElement: each node in the XML document is exposed by an XMLElement object.

        XMLElement Properties
            type: "element". Note that text is added as the text property of an element.
            name: the tag name.
            childElements[]: an array of XMLElements.
            parentElement: the XML Element's parent XML Element.

        XMLElement Methods
            childElement(strElementName): takes the elements tag name and returns the XMLElement
                                          if it's found in the element's children. Otherwise null.
            attribute(strAttributeName): takes the attribute name and returns the value, if found.
                                         Returns an empty string if the attribute isn't found.
            childElementsNamed(strElementName): returns an array of XMLElements that match the elements tag name.
                                                Otherwise an empty array.

Properties:

    rootElement: the rootElement property is the entry point, returning the XMLElement for the first node of the document.
                 To work with an XML document the next thing to do after creating the object is to access the rootElement property
                 and use its properties and methods to navigate through the XML.
*/

function convert(xmlString) {
	this.XML = xmlString;

	this.rootElement = null;

	this.parse = _p;
	if (this.XML && this.XML != "") this.parse();
}

function _p() {
    var rT = new RegExp("<([^>/ ]*)([^>]*)>","g");
    var rTT = new RegExp("<([^>/ ]*)([^>]*)>([^<]*)","g");
    var t = "";
    var txt = "";
    var a = "";
    var e = 0;
    var eL = null;
    if (this.XML.length == 0) return;
    var aEU = this.XML.match(rT);
    var aEUT = this.XML.match(rTT);

    // GRB -- changed iterator start value from 0 to 1, bypassing xml declaration tag.
    for (var i=1; i<aEU.length; i++) {
        t = aEU[i].replace(rT,"$1");
        a = aEU[i].replace(rT,"$2");
        txt = aEUT[i].replace(rTT,"$3").replace(/[\r\n\t ]+/g, " ");
        if (aEU[i].substring(1,2) != "/") {
            if (e == 0) {
                eL = this.rootElement = new _XMLElement(t,a,null,txt);
                e++;
            } else if (aEU[i].substring(aEU[i].length-2,aEU[i].length-1) != "/") {
                eL = eL.childElements[eL.childElements.length] = new _XMLElement(t,a,eL,txt);
                e++;
            } else eL.childElements[eL.childElements.length] = new _XMLElement(t,a,eL,txt);
        } else {
            eL = eL.parentElement;
            e--;
            if (eL) eL.text += txt;
        }
    }
}

function _XMLElement(n, a, p, t) {
    this.type = "element";
    this.name = n;
    this.aStr = a;
    this.attributes = null;
    this.childElements = new Array();
    this.parentElement = p;
    this.text = t;

    this.childElement = _c;
    this.attribute = _a;
    this.childElementsNamed = _n;
}

function _c(n) {
    for (var i=0; i<this.childElements.length; i++) if (this.childElements[i].name == n) return this.childElements[i];
    return null;
}

function _a(n) {
    if (!this.attributes) {
        var ra = new RegExp(" ([^= ]*)=","g");
        if (this.aStr.match(ra) && this.aStr.match(ra).length) {
            var as = this.aStr.match(ra);
            if (!as.length) as = null;
            else for (var j=0; j<as.length; j++) {
                as[j] = new Array(
                    (as[j]+"").replace(/[= ]/g,""),
                    PA(this.aStr, (as[j]+"").replace(/[= ]/g,""))
                                );
            }
            this.attributes = as;
        }
    }
    if (this.attributes) for (var i=0; i<this.attributes.length; i++) if (this.attributes[i][0] == n) return this.attributes[i][1];
    return "";
}

function _n(n) {
    var matches = [];
    for (var i=0; i<this.childElements.length; i++) if (this.childElements[i].name == n) matches.push(this.childElements[i]);
    return matches;
}

function PA(s,n) {
	var s = s +  ">";
	if (s.indexOf(n + "='")>-1) var a = new RegExp(".*" + n + "='([^']*)'.*>");
	else if (s.indexOf(n + '="')>-1) var a = new RegExp(".*" + n + '="([^"]*)".*>');
	return s.replace(a, "$1");
}

// Export the 'convert' function.
exports.convert = convert;
